package com.cqhfan.douyin.filter;

import cn.hutool.core.util.StrUtil;
import com.cqhfan.core.constans.BizConstants;
import com.cqhfan.core.utils.JwtUtil;
import com.cqhfan.douyin.config.TokenProperties;
import io.jsonwebtoken.Claims;
import jakarta.annotation.Resource;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @author 眭传洪
 * @create 2025-07-28 2:26
 */
@Component
public class TokenFilter implements GlobalFilter, Ordered {

    @Resource
    private TokenProperties tokenProperties;

    private final AntPathMatcher pathMatcher = new AntPathMatcher();

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1、白名单直接放行
        ServerHttpRequest request = exchange.getRequest();
        if (tokenProperties.getNoAuthPaths().stream()
                .anyMatch(noAuthPath -> pathMatcher.match(noAuthPath, request.getPath().toString()))) {
            return chain.filter(exchange);
        }

        // 2、获得并解析token
        String token = request.getHeaders().getFirst(BizConstants.USER_TOKEN_HEADER);
        if (StrUtil.isBlank(token)) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        Claims claims = JwtUtil.parseToken(token, tokenProperties.getPublicKey());
        if (claims == null) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }

        // 3、向下传递用户信息
        request.mutate().headers(
                header -> header.add(BizConstants.TOKEN_LOGIN_INFO,
                        claims.get(BizConstants.TOKEN_LOGIN_INFO).toString())
        );

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return Integer.MIN_VALUE;
    }
}
